﻿//#define _TEST_

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ITProject.WebUI.Models;
using System.Xml;
using System.Text;
using System.Security.Cryptography;
using ITProject.Repository.Abstract;
using ITProject.Repository.Concrete;
using ITProject.WebUI.Models.Account;
using ITProject.WebUI.Infrastructure;
using System.Web.Security;
using ITProject.WebUI.Models.Message;
using System.Web.Routing;
using System.IO;
using System.Drawing;
using ITProject.Domain;
using ITProject.Domain.Entities;

namespace ITProject.WebUI.Controllers
{
    public partial class AccountController : Controller
    {
        /// <summary>
        /// Konstruktor przyjmujący repozytorium użytkowników.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="repo">Konkretna implementacja interfejsu repozytorium produktów bindowana przez NinjectFactory.</param>
        public AccountController(IUserRepository repo, IProjectRepository projectRepo)
        {
            _userRepository = repo;
            _projectRepo = projectRepo;
        }
        
        #region "Properites"

        IUserRepository _userRepository;
        IProjectRepository _projectRepo;

        #endregion

        #region "Rejestracja"

        public virtual ActionResult Register()
        {
            AccountRegistrationViewModel vm = new AccountRegistrationViewModel();
            vm.BirthDate = DateTime.Now.AddYears(-20);
            return View(vm);
        }
        
        [HttpPost]
        public virtual ActionResult Register(AccountRegistrationViewModel accountVM)
        {
            if (_userRepository.IsAccountExist(accountVM.Login, accountVM.Mail))
            {
                ModelState.AddModelError("Login","Podany login lub email jest juz zajety");
                return View(accountVM);
            }
            if (accountVM.Password != accountVM.Password2)
            {
                ModelState.AddModelError("Password2", "Hasła nie sa takie same");
                return View(accountVM);
            }
            XmlDocument config = new XmlDocument();
            var path = HttpContext.Server.MapPath("../Infrastructure/AppConfig.xml");
            config.Load(path);
            XmlNode node = config.GetElementsByTagName("salt").Item(0);
            string salt =  node.InnerText;
            accountVM.Password = HashPassword(accountVM.Password);
            var user = AccountRegistrationViewModel.Convert(accountVM);
            // dodano #define w celu możliwości dodawania uczestników bez konieczności wysłania email.
#if _TEST_
            user.State = (byte)UserState.Active;
#else
            user.State = (byte)UserState.Inactive;
#endif
            user = _userRepository.Add(user);
#if !_TEST_
            int size = 15;
            var randomString = MailProvider.RandomString(size);
            _userRepository.AddHash(user.Id, randomString);
            MailProvider.SendActivationLink(user.Id, user.Email, randomString);
#endif
            //do zmiany-do ustalenia, gdzie leci redirect po zarejestrowaniu
            //------------------------
            // testowe zmiany do testowania wysylania wiadomosci
            /*MessageSendViewModel sendViewModel = new MessageSendViewModel();
            sendViewModel.IdReceiver = 1;
            sendViewModel.IdSender = user.Id;
            sendViewModel.NeedReadConfirmation = false;
            sendViewModel.Subject = "Witaj w ITProject";
            sendViewModel.Text = "Wiadomość testowa";
            sendViewModel.controllerResult = MVC.Home.Name;
            sendViewModel.actionResult = MVC.Home.ActionNames.Index;
            return RedirectToAction(MVC.Message.ActionNames.SendMessage, MVC.Message.Name,sendViewModel);*/
            //---------------------------
            return RedirectToAction(MVC.Home.ActionNames.Index, MVC.Home.Name);
        }

        /// <summary>
        /// Metoda do hasowania hasła wydzielona by używać jej nie tylko w rejestracji.
        /// Autor: Jakub Szatkowski
        /// Ciało metody: Michał Gajewski
        /// </summary>
        /// <param name="password">Nie zaszyfrowane hasło.</param>
        /// <returns>Zaszyfrowane hasło.</returns>
        private string HashPassword(string password)
        {
            XmlDocument config = new XmlDocument();
            var path = HttpContext.Server.MapPath("../Infrastructure/AppConfig.xml");
            config.Load(path);
            XmlNode node = config.GetElementsByTagName("salt").Item(0);
            string salt = node.InnerText;
            return Helpers.PasswordHashProvider(password, salt);
        }

        public virtual ActionResult Activate(string hash)
        {
            _userRepository.ActivateAccount(hash);
            return RedirectToAction(MVC.Account.ActionNames.Login, new {message="Konto zostało aktywowane"});
        }
        #endregion

        #region "Logowanie"

        public virtual ActionResult Login(string message)
        {
            if (!string.IsNullOrEmpty(message))
            {
                ViewBag.Notification = message;
            }
            return View(new BaseViewModel());
        }

        [HttpPost]
        public virtual ActionResult Login(FormCollection collection)
        {
            string login = collection["login"];
            string PlainPassword = collection["password"];
            // edycja Jakub Szatkowski - wydzielenie funkcji na hasowanie
            string password = HashPassword(PlainPassword);
            var user = _userRepository.GetUserByLogin(login);
            bool remember;
            if (collection["Remember"] == "false")
            {
                remember = false;
            }
            else
            {
                remember = true;
            }
            if (user != null  && user.Password == password)
            {
                if (user.State == (byte)UserState.Active)
                {
                    FormsAuthentication.SetAuthCookie(login, remember);
                    return RedirectToAction(MVC.Home.ActionNames.Index, MVC.Home.Name);
                }
                else
                {
                    ViewBag.Notification = "Konto jest niekatywne";
                    return View(new BaseViewModel());
                }
            }
            else
            {
                ViewBag.Notification = "Niepoprawny login lub haslo";
                //viewModel.Notification = "Niepoprawny login lub haslo";
                return View(new BaseViewModel());
            }
            
        }

        public virtual ActionResult Logout()
        {
            FormsAuthentication.SignOut();
            return RedirectToAction(MVC.Home.ActionNames.Index, MVC.Home.Name);
        }
        #endregion

        #region edycja
        /// <summary>
        /// Autor: Natalia Wyczislok
        /// Metoda zwraca instancje modelu UserInformation do widoku edycji profilu
        /// </summary>
        /// <returns></returns>
        public virtual ActionResult Edit()
        {
            var user = _userRepository.GetUserByLogin(User.Identity.Name);
            var profil = _userRepository.GetProfilById(user.Id);
            UserInformationViewModel u = UserInformationViewModel.Convert(user, profil);
            
            return View(u);
        }

        /// <summary>
        /// Autor: Natalia Wyczislok
        /// Modyfikacja: Jakub Szatkowski
        /// </summary>
        /// <param name="uivm"></param>
        /// <returns></returns>
        [HttpPost]
        public virtual ActionResult Edit(UserInformationViewModel uivm)
        {
            // Modyfikacja Jakub Szatkowski, user jako globalna zmienna metody
            User user=_userRepository.GetUserByLogin(User.Identity.Name);
            if ((uivm.OldPassword != null && uivm.OldPassword != "") || (uivm.PasswordNew2 != null && uivm.PasswordNew2 != "") || (uivm.NewPassword != null && uivm.NewPassword != ""))
            {
                string hashpassword = HashPassword(uivm.OldPassword);
                if (hashpassword != user.Password)
                {
                    ModelState.AddModelError("OldPassword", "Podałeś niepoprawne hasło, sprawdź czy nie masz włączonego Caps Locka");
                    return View(uivm);
                }
                if (uivm.NewPassword == null || uivm.NewPassword == "")
                {
                    ModelState.AddModelError("NewPassword","Nie podałeś nowego hasła");
                    return View(uivm);
                }
                if (uivm.PasswordNew2 == null || uivm.PasswordNew2 == "")
                {
                    ModelState.AddModelError("PasswordNew2","Nowe hasło należy powtórzyć");
                    return View(uivm);
                }
                if (uivm.PasswordNew2 != uivm.NewPassword)
                {
                    ModelState.AddModelError("PasswordNew2","Podałeś dwa różne nowe hasła");
                    return View(uivm);
                    }
            }
            if (uivm.AvatarDelete)
            {
                string OldAvatar = uivm.AvatarName;
                if (OldAvatar != null) // usun avatar
                {
                    string oldAvPath = Path.Combine(HttpContext.Server.MapPath("/UserFiles/Avatars/"), OldAvatar);
                    if (System.IO.File.Exists(oldAvPath))
                        System.IO.File.Delete(oldAvPath);
                    uivm.AvatarName = null;
                }

            }
            if (uivm.AvatarPath != null)
            {
                if (uivm.AvatarPath.ContentLength > 0)
                {
                    string OldAvatar = uivm.AvatarName;

                    uivm.AvatarName = Path.GetFileName(uivm.AvatarPath.FileName);
                    int indexOfDot = uivm.AvatarName.LastIndexOf('.');
                    uivm.AvatarName = uivm.AvatarName.Insert(indexOfDot, DateTime.Now.ToString()).Replace(':', '.').Replace(" ", "");
                    var path = Path.Combine(HttpContext.Server.MapPath("/UserFiles/Avatars"), uivm.AvatarName);
                    
                    if (uivm.AvatarPath.ContentType != "image/jpeg" && uivm.AvatarPath.ContentType != "image/png" && uivm.AvatarPath.ContentType != "image/gif")
                    {
                        ModelState.AddModelError("AvatarPath","Plik avatara musi być obrazkiem");
                        return View(uivm);
                    }
                    else
                    {
                        using (Image image = Image.FromStream(uivm.AvatarPath.InputStream, true, true))
                        {
                            if (image.Width < UserInformationViewModel.MaxAvatarWidth && image.Height < UserInformationViewModel.MaxAvatarHeight)
                            {
                                // Modyfikacja: Jakub Szatkowski, usuwanie starego avataru,modyfikacja: Natalia Wyczislok
                                if (OldAvatar != null) // usun avatar
                                {
                                    string oldAvPath = Path.Combine(HttpContext.Server.MapPath("/UserFiles/Avatars/"),OldAvatar);
                                    if (System.IO.File.Exists(oldAvPath))
                                        System.IO.File.Delete(oldAvPath);
                                }
                                //-------------------------------
                                uivm.AvatarPath.SaveAs(path);
                            }
                            else
                            {
                                ModelState.AddModelError("AvatarPath","Obraz nie może być większy niż " + UserInformationViewModel.MaxAvatarWidth + "px X " + UserInformationViewModel.MaxAvatarHeight + "px");
                                return View(uivm);
                            }
                        }
                    }
                }
                else
                    uivm.AvatarPath = null;
                
                    

            }
            var userr = uivm.ConvertToUser();
            var profil = uivm.ConvertToProfil();
            _userRepository.EditUserData(userr, profil,User.Identity.Name);


            return View(uivm);
        }

        #endregion

        #region PobranieInformacji
        /// <summary>
        /// funkcja zwraca do vidoku UserList liste podstawowych informacji o użytkownikach w zależności od strony na której jesteśmy
        /// </summary>
        /// <param name="str">strona widoku</param>
        /// <returns></returns>
        public virtual ViewResult UserList(int str=1)
        {
            str -= 1;
            if (str < _userRepository.getCountSite())
            {
                IEnumerable<User> users = _userRepository.GetAllUsers(str);
                IEnumerable<Profil> profil = _userRepository.GetAllProfil();
                IEnumerable<UserListViewModel> userinformation = UserListViewModel.Convert(users,profil, _userRepository);
                return View(userinformation);
            }
            else
                return View("NotFindView");
        }
        /// <summary>
        /// Metoda wysyła do widoku profilu, informacjie o danym użytkowniku
        /// </summary>
        /// <param name="Login">Login użytkownika</param>
        /// <returns></returns>
        [Authorize]
        public virtual ViewResult Profil(string Login)
        {
            User u = _userRepository.GetUserByLogin(Login);
            if (u == null)
                return View("NotFindView");
            Profil p = _userRepository.GetProfilById(u.Id);
            List<string> up;
            List<string> sp;
            _projectRepo.GetUserProject(u.Id,out up,out sp);
            UserProfilViewModel UPvm = UserProfilViewModel.Convert(u, p,_userRepository,up,sp);
            return View(UPvm);
        }
        #endregion
    }
}

